<style lang="scss" scoped>
.list-move {
  transition: all 0.5s ease;
}
</style>

<template>
  <div class="root-flex-page p-2">
    <p
      class="mb-3 flex flex-shrink-0 items-center border-b-2 border-blue-400 pb-2 text-xl font-bold text-blue-500"
    >
      <Icon
        v-if="ISocket?.status === 'OPEN'"
        name="majesticons:status-online-line"
      />
      <Icon
        v-else-if="ISocket?.status === 'CONNECTING'"
        name="line-md:loading-alt-loop"
      />
      <Icon v-else name="majesticons:status-offline-line" color="#ee1d6a" />

      <span class="ml-1 truncate">排队列表</span>

      <Icon class="ml-1" name="arcticons:genshin-impact" />
      <button class="btn-secondary btn-sm btn ml-auto" @click="init">
        刷新
      </button>
      <button
        class="btn-primary btn-sm btn ml-2"
        @click="editOpen = true"
        v-if="!isQueue"
      >
        我要排队
      </button>
    </p>
    <div class="relative flex-1 overflow-y-scroll">
      <transition-group
        :css="false"
        @enter="onEnter"
        @leave="onLeave"
        name="list"
      >
        <div
          v-for="(item, index) in list"
          :key="item.name"
          :data-index="index"
          class="box-content flex h-6 cursor-pointer select-none items-center px-2 py-2"
        >
          <span
            class="mr-2 w-6 flex-shrink-0 rounded-full bg-blue-300 text-center text-white shadow"
          >
            {{ index + 1 }}
          </span>
          <span class="truncate font-bold tracking-widest text-blue-400">
            {{ item.name }}
          </span>
        </div>
        <div
          v-if="total > CONF_DEFINE_PAGESIZE"
          class="box-content flex h-6 cursor-pointer select-none items-center px-2 py-2"
        >
          <span
            class="mr-2 h-2 w-2 flex-shrink-0 rounded-full bg-blue-700 text-center text-white shadow"
          ></span>
          <span
            class="mr-2 h-2 w-2 flex-shrink-0 rounded-full bg-blue-700 text-center text-white shadow"
          ></span>
          <span
            class="mr-2 h-2 w-2 flex-shrink-0 rounded-full bg-blue-700 text-center text-white shadow"
          ></span>
          <span class="truncate font-bold tracking-widest text-blue-700">
            等 {{ total }} 人
          </span>
        </div>
      </transition-group>

      <button
        class="btn-primary btn-sm btn absolute bottom-0 right-0"
        @click="router.push({ name: 'message-leave' })"
      >
        匿名留言
      </button>
      <van-watermark
        v-if="isMounted"
        content="一柯小白菜"
        :full-page="false"
        :width="140"
        :height="80"
        :z-index="-1"
        :opacity="0.4"
      />
    </div>

    <van-overlay
      v-if="!isQueue"
      :show="editOpen"
      :lock-scroll="false"
      @click="editOpen = false"
    >
      <div
        class="absolute bottom-0 h-3/4 w-full rounded-t-xl bg-white"
        @click.stop
      >
        <van-form
          ref="FormRef"
          label-align="top"
          class="flex h-full flex-col p-2"
        >
          <p class="mb-2 font-bold tracking-widest">排队</p>
          <div class="flex-1 overflow-y-scroll">
            <van-field
              v-model="editItem.name"
              label="b站昵称"
              placeholder="b站昵称"
              :rules="[{ required: true, message: '请填写b站昵称' }]"
            />
            <van-field
              v-model="editItem.account"
              label="游戏账号"
              placeholder="游戏账号"
            />
            <van-field
              v-model="editItem.uid"
              label="UID"
              placeholder="UID"
              :rules="[
                { pattern: uidPattren, message: '请填写正确的UID（仅限国服）' },
              ]"
            />

            <van-field
              v-model="editItem.remark"
              rows="3"
              autosize
              label="备注/留言"
              type="textarea"
              maxlength="252"
              placeholder="请输入留言"
              show-word-limit
            />
          </div>
          <div class="mt-auto flex w-full flex-shrink-0 gap-4">
            <button class="btn-warning btn flex-1" @click="editOpen = false">
              取消
            </button>
            <button class="btn-primary btn flex-1" @click="onSubmit">
              确定
            </button>
          </div>
        </van-form>
      </div>
    </van-overlay>
  </div>
</template>

<script lang="ts" setup>
import { getQueueList, addQueue, type IQueueUser } from '~/api'
import { type FormInstance } from 'vant'

interface IData {
  list: IQueueUser[]
  editOpen: boolean
  editItem: Partial<IQueueUser>
  isQueue: boolean
  total: number
  isMounted: boolean
}

const router = useRouter()
const { $gsap } = useNuxtApp()
const uidPattren = /^[12]\d{8}$/
const FormRef = ref<FormInstance>()
const { key } = useGlobalState()
const data = reactive<IData>({
  list: [],
  editOpen: false,
  editItem: {},
  isQueue: false,
  total: 0,
  isMounted: false,
})

const WS_URL = (import.meta.env.VITE_BASW_WS_API as string) + '/queue'
let ISocket = ref<any>()

const onEnter = (el: any, done: () => void) => {
  $gsap.from(el, {
    opacity: 0,
    y: 100,
    clipPath: 'inset(0 100% 0 0%)',
    delay: el.dataset.index * 0.15,
    onComplete: done,
  })
}

const onLeave = (el: any, done: () => void) => {
  const animate = $gsap.timeline()
  animate
    .to(el, {
      opacity: 0,
      clipPath: 'inset(0 100% 0 0%)',
    })
    .to(el, {
      height: 0,
      paddingTop: 0,
      paddingBottom: 0,
      onComplete: done,
    })
}

async function onSubmit() {
  await FormRef.value?.validate()
  const Item = useCloneDeep(data.editItem as IQueueUser)
  await init()
  Item.sort = data.list.length
  const { id } = await addQueue(Item)
  Object.assign(data, {
    editOpen: false,
    editItem: {},
  })
  await nextTick()
  Item.id = id
  if (data.total < CONF_DEFINE_PAGESIZE) {
    data.list.push(Item)
  }
  data.total += 1
  // localStorage.setItem('XOXOXOPAC', new Date().toLocaleDateString())
  showSuccessToast(`排队成功`)
}

async function init() {
  const { list, total } = await getQueueList()
  Object.assign(data, { list, total })
}

onBeforeMount(() => {
  init()
})

onMounted(() => {
  data.isMounted = true
  ISocket.value = useWebSocket(WS_URL, {
    onConnected: (ws) => {
      ws.send(key.value)
    },
    onMessage: (ws, message) => {
      const { list, total } = JSON.parse(message.data)
      Object.assign(data, { list, total })
    },
    autoReconnect: {
      retries: 10,
      delay: 1000,
      onFailed() {
        showFailToast('ws:连接失败，无法实时更新数据！')
      },
    },
  })
})

const { list, editOpen, editItem, isQueue, total, isMounted } = {
  ...toRefs(data),
}
</script>
